// 创建Observer类
// 1. 负责把data选项中的属性转换成响应式数据
// 2. data中某个属性也是对象，把该属性转换成响应式数据
// 3. 数据变化发送通知

class Observer {
    constructor(data) {
        this.walk(data);
    }
    walk(data) {
        // 判断data是否有值且对象, 如果不是对象则直接返回
        if (!data || typeof data !== "object") {
            return;
        }
        // 遍历data对象的所有属性,(如果接收的data是对象则将对象内部的值设置为响应式的)
        Object.keys(data).forEach(key => {
            this.defineReactive(data, key, data[key]);
        });
    }
    // 1. 传入的data 2. 属性 3. 属性对应的值
    defineReactive(obj, key, val) {
        const self = this;
        // 负责收集依赖, 并发送通知;
        const dep = new Dep();
        // 接收到的值如果是对象则调用walk方法,将val内部属性转换成响应式数据
        this.walk(val);
        // 注意: 这里拦截obj的属性key,如果下面get的时候是获取的obj[key]会陷入一个死循环
        Object.defineProperty(obj, key, {
            // 可枚举
            enumerable: true,
            // 可配置
            configurable: true,
            get() {
                Dep.target && dep.addSub(Dep.target);
                // 这里必须是返回val,如果返回自身的obj[key]会无限触发get,陷入死循环
                return val;
            },
            set(newValue) {
                if (newValue === val) {
                    return;
                }
                val = newValue;
                // 把重新赋值的如果是个新对象内部的值也设置为响应式的
                self.walk(val);
                // 发送通知
                dep.notify();
            },
        });
    }
}
